package by.demchenko.sample.services.impl;

import by.demchenko.sample.dataaccess.base.ResultDao;
import by.demchenko.sample.datamodel.Course;
import by.demchenko.sample.datamodel.Person;
import by.demchenko.sample.datamodel.Result;
import by.demchenko.sample.datamodel.Schedule;
import by.demchenko.sample.services.ResultService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.inject.Inject;
import javax.persistence.metamodel.SingularAttribute;
import java.util.List;

@Service
public class ResultServiceImpl implements ResultService {
    private static final Logger LOGGER = LoggerFactory.getLogger(ResultServiceImpl.class);

    @Inject
    ResultDao dao;

    @Override
    public Result get(Integer id) {
        return dao.getById(id);
    }

    public Result get(Person student, Course course) {
        return dao.getResult(student, course);
    }

    @Override
    public List<Result> getResults(SingularAttribute<Result, ?> attr, boolean ascending, int startRecord, int pageSize) {
        return dao.getResults(attr, ascending, startRecord, pageSize);
    }

    @Override
    public void save(Result result) {
        dao.insert(result);
    }

    @Override
    public void saveOrUpdate(Result result) {
        if (result.getId() == null) {
            LOGGER.debug("Save new: {}", result);
            dao.insert(result);
        } else {
            LOGGER.debug("Update: {}", result);
            dao.update(result);
        }
    }


    @Override
    public void deleteAll() {
        LOGGER.debug("Remove all results");
        dao.deleteAll();
    }

    @Override
    public void assignAGrade(Person student, Schedule schedule, int grade) {
        if (possibleToAssignAGrade(student, schedule.getCourse())) {
            Result result = new Result();
            result.setStudent(student);
            result.setSchedule(schedule);
            result.setGrade(grade);
            dao.insert(result);
        }
    }

    @Override
    public int getGrade(Person student, Course course) {
        Result result = dao.getResult(student, course);
        if (result != null) {
            return dao.getResult(student, course).getGrade();
        }
        return 0;
    }

    @Override
    public List<Result> getGrades(Person student) {
        return dao.getResultsByStudent(student);
    }

    @Override
    public int getCount() {
        return dao.getCount();
    }

    @Override
    public void delete(Result result) {
        dao.delete(result.getId());
    }

    @Override
    public List<Result> getGradesByCourse(Schedule schedule) {
        return dao.getResultsByCourse(schedule);
    }


    private boolean possibleToAssignAGrade(Person student, Course course) throws IllegalArgumentException {
        if (!dao.canAssignTheGrade(student, course)) {
            throw new IllegalArgumentException(
                    String.format("Can't assign a grade to '%s' - not enrolled on the course '%s'!",
                            student.getFullName(), course.getName()));
        }
        if (dao.getResult(student, course) != null) {
            throw new IllegalArgumentException(
                    String.format("Can't assign a grade to '%s', already has a grade on course '%s'!",
                    student.getFullName(), course.getName()));
        }
        return true;
    }
}
